wayland: Warn when an application tries to map popup incorrectly
authorJonas Ådahl <jadahl@gmail.com>
Fri, 2 Sep 2016 10:51:34 +0000 (18:51 +0800)
committerJonas Ådahl <jadahl@gmail.com>
Fri, 2 Sep 2016 10:56:03 +0000 (18:56 +0800)
When a popup is mapped but will not be the top most popup (for example
the parent is not the current top most popup, or if there already is a
popup mapped but the parent is a toplevel), warn and ignore it instead
of continuing, as continuing would be a protocol violation.

https://bugzilla.gnome.org/show_bug.cgi?id=770745

gdk/wayland/gdkdisplay-wayland.h
gdk/wayland/gdkwindow-wayland.c

index ace514349d1e595c816317b1e53c1e9ca04b6f36..a68940f5b8d17dde128e44bb8bea9996adbfa1a6 100644 (file)
@@ -90,6 +90,8 @@ struct _GdkWaylandDisplay
   /* Keep a list of orphaned dialogs (i.e. without parent) */
   GList *orphan_dialogs;
 
+  GList *current_popups;
+
   struct wl_cursor_theme *scaled_cursor_themes[GDK_WAYLAND_THEME_SCALES_COUNT];
   gchar *cursor_theme_name;
   int cursor_theme_size;
index 98d666dd710105aa95966b9eb7edbfbf48841a59..ccd3bc4f32ad9d2c69c82441f82aa924778f8406 100644 (file)
@@ -1971,6 +1971,14 @@ gdk_wayland_window_create_xdg_popup (GdkWindow      *window,
       g_warning ("Can't map popup, already mapped");
       return;
     }
+  if ((display->current_popups &&
+       g_list_last (display->current_popups)->data != parent) ||
+      (!display->current_popups &&
+       !parent_impl->display_server.xdg_toplevel))
+    {
+      g_warning ("Tried to map a popup with a non-top most parent");
+      return;
+    }
 
   impl->display_server.xdg_surface =
     zxdg_shell_v6_get_xdg_surface (display->xdg_shell,
@@ -2000,6 +2008,8 @@ gdk_wayland_window_create_xdg_popup (GdkWindow      *window,
   zxdg_popup_v6_grab (impl->display_server.xdg_popup, seat, serial);
 
   wl_surface_commit (impl->display_server.wl_surface);
+
+  display->current_popups = g_list_append (display->current_popups, window);
 }
 
 static struct wl_seat *
@@ -2362,6 +2372,8 @@ gdk_wayland_window_hide_surface (GdkWindow *window)
         {
           zxdg_popup_v6_destroy (impl->display_server.xdg_popup);
           impl->display_server.xdg_popup = NULL;
+          display_wayland->current_popups =
+            g_list_remove (display_wayland->current_popups, window);
         }
       if (impl->display_server.xdg_surface)
         {